//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:xzh 
// 
// Create Date: 2020/09/10 10:42:44
// Design Name: 
// Module Name: sop_eop_to_axi
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: ll\u8f6caxi,\u652f\u6301\u8fde\u7eed\u7684ll\u8f93\u5165,\u8f6c\u5316\u540e\u7684axi_stream\u6570\u636e\u5e27\u95f4\u9694\u81f3\u5c11\u4e3a1clk,\u6a21\u5757\u6ca1\u6709\u7f13\u5b58\u529f\u80fd,\u6240\u4ee5\u5916\u90e8\u63a5\u53d7\u4e0d\u4e86\u5c31\u6574\u4e2aemac\u5e27\u4e22\u5f03 
// 
// Revision:
// Revision 0.01 - File Created
// Revision 0.02 - packet mode
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
`include "top_define.v"
module sop_eop_to_axi(
    input                    clk             ,
    input                    rst_n           ,
    input      [9:0]        ram_2p_cfg_register,
    //ll in
    input      [ 255:   0]   pkt_tx_data         ,
    input                    pkt_tx_eop          ,
    input      [   4:   0]   pkt_tx_mod          ,
    //input                    pkt_tx_sop          ,
    input                    pkt_tx_dval         ,
	(*mark_debug = "true"*)output                   pkt_tx_rdy          ,
    //axi_stream out
    input                         out_axis_tready     ,
    output  reg    [ 255:   0]    out_axis_tdata      ,
    output  reg                   out_axis_tvalid     ,
    output  reg    [  31:   0]    out_axis_tkeep      ,
    output  reg                   out_axis_tlast      
);

reg pkt_tx_dval_dl1 ;
reg pkt_tx_eop_dl1 ;

(*mark_debug = "true"*) reg [31:0]  axis_tkeep_temp ;
reg [255:0] out_axis_tdata_temp ;

//fifo
(*mark_debug = "true"*) reg  fifo_we ;
(*mark_debug = "true"*) reg  fifo_rd_temp ;
(*mark_debug = "true"*) wire fifo_rd ;
// (*mark_debug = "true"*) reg  fifo_rd_dl1 ;
(*mark_debug = "true"*) wire fifo_full ;  
(*mark_debug = "true"*) wire fifo_empty ; 
reg  [288:0] fifo_data_i ;
wire [288:0] fifo_data_o ;
wire prog_full;
reg [7:0] pkt_cnt;
//(*mark_debug = "true"*) reg discard_state ;

//\u6253\u62cd
always @(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        pkt_tx_dval_dl1 <= 1'b0 ;
        pkt_tx_eop_dl1  <= 1'b0 ;
    end
    else begin
        pkt_tx_dval_dl1 <= pkt_tx_dval ;
        pkt_tx_eop_dl1  <= pkt_tx_eop ;
    end
end

//out_axis_tdata
always @( posedge clk ) 
begin
	if ( pkt_tx_dval == 1'b1 )  
		out_axis_tdata_temp <= { pkt_tx_data[ 7: 0], pkt_tx_data[15: 8], pkt_tx_data[23:16], pkt_tx_data[31:24], pkt_tx_data[39:32]
		                         , pkt_tx_data[47:40],  pkt_tx_data[55:48], pkt_tx_data[63:56], pkt_tx_data[71:64], pkt_tx_data[79:72], pkt_tx_data[87:80], pkt_tx_data[95:88]
		                         , pkt_tx_data[103:96], pkt_tx_data[111:104], pkt_tx_data[119:112], pkt_tx_data[127:120] , pkt_tx_data[135:128] , pkt_tx_data[143:136] , pkt_tx_data[151:144] ,
		                          pkt_tx_data[159:152] , pkt_tx_data[167:160] , pkt_tx_data[175:168] , pkt_tx_data[183:176] , pkt_tx_data[191:184] , pkt_tx_data[199:192] , pkt_tx_data[207:200] ,
		                           pkt_tx_data[215:208] , pkt_tx_data[223:216] , pkt_tx_data[231:224] , pkt_tx_data[239:232] , pkt_tx_data[247:240] , pkt_tx_data[255:248] } ;
    else
		out_axis_tdata_temp <= 256'b0 ;	
end 

//axis_tkeep_temp
always @ ( posedge clk or negedge rst_n )  begin
	if ( rst_n == 1'b0 )
		axis_tkeep_temp <= 32'b0 ;
    else if(pkt_tx_dval == 1'b1 ) begin
		case( {pkt_tx_eop , pkt_tx_mod} )
			6'b1_10000 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_1111_1111_1111_1111;
			6'b1_01111 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0111_1111_1111_1111;
			6'b1_01110 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0011_1111_1111_1111;
			6'b1_01101 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0001_1111_1111_1111;
			6'b1_01100 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_1111_1111_1111;
			6'b1_01011 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0111_1111_1111;
			6'b1_01010 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0011_1111_1111;
			6'b1_01001 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0001_1111_1111;
			6'b1_01000 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_1111_1111;
			6'b1_00111 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0111_1111;
			6'b1_00110 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0011_1111;
			6'b1_00101 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0001_1111;
			6'b1_00100 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0000_1111;
			6'b1_00011 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0000_0111;
			6'b1_00010 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0000_0011;
			6'b1_00001 : axis_tkeep_temp <= 32'b0000_0000_0000_0000_0000_0000_0000_0001;

			6'b1_00000 : axis_tkeep_temp <= 32'b1111_1111_1111_1111_1111_1111_1111_1111 ;
			6'b1_11111 : axis_tkeep_temp <= 32'b0111_1111_1111_1111_1111_1111_1111_1111 ;
			6'b1_11110 : axis_tkeep_temp <= 32'b0011_1111_1111_1111_1111_1111_1111_1111 ;
			6'b1_11101 : axis_tkeep_temp <= 32'b0001_1111_1111_1111_1111_1111_1111_1111 ;
			6'b1_11100 : axis_tkeep_temp <= 32'b0000_1111_1111_1111_1111_1111_1111_1111 ;
			6'b1_11011 : axis_tkeep_temp <= 32'b0000_0111_1111_1111_1111_1111_1111_1111 ;
			6'b1_11010 : axis_tkeep_temp <= 32'b0000_0011_1111_1111_1111_1111_1111_1111 ;
			6'b1_11001 : axis_tkeep_temp <= 32'b0000_0001_1111_1111_1111_1111_1111_1111 ;
			6'b1_11000 : axis_tkeep_temp <= 32'b0000_0000_1111_1111_1111_1111_1111_1111 ;
			6'b1_10111 : axis_tkeep_temp <= 32'b0000_0000_0111_1111_1111_1111_1111_1111 ;
			6'b1_10110 : axis_tkeep_temp <= 32'b0000_0000_0011_1111_1111_1111_1111_1111 ;
			6'b1_10101 : axis_tkeep_temp <= 32'b0000_0000_0001_1111_1111_1111_1111_1111 ;
			6'b1_10100 : axis_tkeep_temp <= 32'b0000_0000_0000_1111_1111_1111_1111_1111 ;
			6'b1_10011 : axis_tkeep_temp <= 32'b0000_0000_0000_0111_1111_1111_1111_1111 ;
			6'b1_10010 : axis_tkeep_temp <= 32'b0000_0000_0000_0011_1111_1111_1111_1111 ;
			6'b1_10001 : axis_tkeep_temp <= 32'b0000_0000_0000_0001_1111_1111_1111_1111 ;
			default :  axis_tkeep_temp <= 32'b1111_1111_1111_1111_1111_1111_1111_1111 ;
		endcase
	end
    else
        axis_tkeep_temp <= 32'b0 ;
end

//-------------------------------------
//fifo \u5199 clk
//-------------------------------------
//fifo_data_i
// _ _ _ 1 _ _ _ _ _ _32_ _ _ _ _ _ _ 256 _ _ _
//|     288    |    287~256    |     255~0     |
//|___  eop  __|___  tkeep  ___|___  tdata  ___|
always @( posedge clk ) begin
    if (pkt_tx_dval_dl1==1'b1) begin
        fifo_data_i <= { pkt_tx_eop_dl1 , axis_tkeep_temp , out_axis_tdata_temp } ;
    end
    else begin
        fifo_data_i <= 289'b0 ;
    end
end

//fifo_we
always @( posedge clk or negedge rst_n ) 
begin
	if ( rst_n == 1'b0 ) 
		fifo_we <= 1'b0 ;
	else if ( pkt_tx_dval_dl1 == 1'b1 && fifo_full == 1'b0 ) 
		fifo_we <= 1'b1 ;
	else
		fifo_we <= 1'b0 ;
end 

//-------------------------------------
//fifo \u8bfb clk
//-------------------------------------
always @ ( posedge clk or negedge rst_n )  begin
	if ( rst_n == 1'b0 )
		fifo_rd_temp <= 1'b0 ;
	else if (fifo_data_o[288] & fifo_rd) 
		fifo_rd_temp <= 1'b0 ;
	else if (( pkt_cnt != 8'b0 ) || (fifo_full == 1'b1))
		fifo_rd_temp <= 1'b1 ;
    else
		fifo_rd_temp <= 1'b0 ;
end

assign fifo_rd = fifo_rd_temp & out_axis_tready;

//axi_stream out
always @( posedge clk or negedge rst_n ) begin
    if (rst_n==1'b0) begin
        out_axis_tdata  <= 256'b0 	;
        out_axis_tvalid <= 1'b0 	;
        out_axis_tkeep  <= 32'b0 	;
        out_axis_tlast  <= 1'b0 	;
    end
	else if (out_axis_tready == 1'b0) begin
        out_axis_tdata  <= out_axis_tdata 	;
        out_axis_tvalid <= out_axis_tvalid 	;
        out_axis_tkeep  <= out_axis_tkeep 	;
        out_axis_tlast  <= out_axis_tlast 	;
	end
    else if (fifo_rd==1'b1 ) begin
        out_axis_tdata  <= fifo_data_o[255:0]   ;
        out_axis_tvalid <= 1'b1                 ;
        out_axis_tkeep  <= fifo_data_o[287:256] ;
        out_axis_tlast  <= fifo_data_o[288]     ;        
    end
    else begin
        out_axis_tdata  <= 256'b0 ;
        out_axis_tvalid <= 1'b0   ;
        out_axis_tkeep  <= 32'b0  ;
        out_axis_tlast  <= 1'b0   ;
    end
end

//pkt_cnt
always @( posedge clk or negedge rst_n ) begin
	if (rst_n == 1'b0) begin
		pkt_cnt <= 8'b0;
	end
	else if (fifo_data_i[288] == 1'b1 && fifo_data_o[288] == 1'b1 && fifo_rd == 1'b1) begin
		pkt_cnt <= pkt_cnt;
	end
	else if (fifo_data_i[288] == 1'b1) begin
		pkt_cnt <= pkt_cnt + 8'b1;
	end
	else if (fifo_data_o[288] == 1'b1 && fifo_rd == 1'b1) begin
		pkt_cnt <= pkt_cnt - 8'b1;
	end
	else begin
		pkt_cnt <= pkt_cnt;
	end
end

//
// always @( posedge clk or negedge rst_n ) begin
//     if (rst_n==1'b0) begin
// 		discard_state <= 1'b0 ;
// 	end
// 	else if ( fifo_rd == 1'b1 && fifo_rd_dl1 == 1'b0 && discard == 1'b1 ) begin
// 		discard_state <= 1'b1 ;
// 	end
// 	else if ( fifo_rd == 1'b0 && fifo_rd_dl1 == 1'b1 ) begin
// 		discard_state <= 1'b0 ;
// 	end
// 	else begin
// 		discard_state <= discard_state ; 
// 	end
// end


//\u9996\u5b57\u7f6e\u51fa\u540c\u6b65FIFO
`ifdef ASIC
pkt_2_axi_fifo_fwft U_pkt_2_axi_asyn_fifo_fwft(
    .clk(clk),
    .clr(rst_n),
    .ram_2p_cfg_register(ram_2p_cfg_register),
    .w_data(fifo_data_i),
    .w_we(fifo_we),
    .w_full(fifo_full),
    .w_afull(prog_full),
    .r_data(fifo_data_o),
    .r_re(fifo_rd),
    .r_empty(fifo_empty),
    .r_aempty()
    );
`else
pkt_2_axi_asyn_fifo U_pkt_2_axi_asyn_fifo (
  .clk(clk),              // input wire clk
  .rst(~rst_n),        // input wire rst
  .din(fifo_data_i),        // input wire [288 : 0] din
  .wr_en(fifo_we),    // input wire wr_en
  .rd_en(fifo_rd),    // input wire rd_en
  .dout(fifo_data_o),      // output wire [288 : 0] dout
  .full(fifo_full),      // output wire full
  .empty(fifo_empty),    // output wire empty
  .prog_full(prog_full)  // output wire prog_full
);
`endif
assign pkt_tx_rdy = ~prog_full;

//*********************mark debug*****************************
reg [13:0] fifo_occupy;

(*mark_debug = "true"*) reg [13:0] max_occupy;
//\u8ba1\u7b97FIFO\u5360\u7528
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        fifo_occupy <= 14'b0;
    end
    else if (fifo_we & fifo_rd) begin
        fifo_occupy <= fifo_occupy;
    end
    else if (fifo_we) begin
        fifo_occupy <= fifo_occupy + 1'b1;
    end
    else if (fifo_rd) begin
        fifo_occupy <= fifo_occupy - 1'b1;
    end
    else begin
        fifo_occupy <= fifo_occupy;
    end
end

//\u8ba1\u7b97\u6700\u5927\u5360\u7528
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        max_occupy <= 14'b0;
    end
    else if (fifo_occupy >= max_occupy) begin
        max_occupy <= fifo_occupy;
    end
    else begin
        max_occupy <= max_occupy;
    end
end

// (*mark_debug = "true"*) reg [31:0] discard_axi_out_cnt ;

// always @( posedge clk or negedge rst_n ) begin
//     if (rst_n==1'b0) begin
// 		discard_axi_out_cnt <= 32'd0 ;
// 	end
// 	else if ( fifo_rd_dl1==1'b1 && discard_state == 1'b1 && fifo_data_o[288] == 1'b1 ) begin
// 		discard_axi_out_cnt <= discard_axi_out_cnt + 32'd1 ;
// 	end
// 	else begin
// 		discard_axi_out_cnt <= discard_axi_out_cnt ;
// 	end
// end
//*********************end mark debug*****************************

endmodule 
